﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace GabageFactory.Models
{
    public class ReportingReposity : Reposity
    {
        public IEnumerable<int> ListYears()
        {
            var years = (from r in _dataContext.analysis_reporting_lists
                        select  r.date.Year).Distinct();

            years = from r in years
                    orderby r descending
                    select r;
            


            foreach (int y in years)
            {
                
                yield return y;
            }
        }

        public List<StackReporting> QueryStackReportings(long factoryId, long stackId, DateTime begin, DateTime end, Pagination pagination)
        {
            var stackReportings = (from r in _dataContext.analysis_reporting_lists
                                   from f in _dataContext.Factories
                                   from s in _dataContext.Stacks
                                   from d in _dataContext.stack_analysis_details
                                   where r.status == 3 && f.Id == r.factoryId && r.type == 1 && r.stackId == s.Id && r.stackId == stackId && r.date >= begin && r.date <= end && r.id == d.id
                                   select new StackReporting
                                   {
                                       id = r.id,
                                       date = r.date,
                                       ardealite = d.ardealite,
                                       backwater = d.backwater,
                                       ditch = d.ditch,
                                       drain = d.drain,
                                       piezometerbase = d.piezometerbase,
                                       piezometerwell = d.piezometerwell,
                                       settle = d.settle,
                                       water = d.water,
                                       FactoryName = f.Name,
                                       StackName = s.Name
                                   });

            stackReportings = from r in stackReportings
                         orderby r.date descending
                         select r;

            return Pagination<StackReporting>(stackReportings, pagination);
        }

        public List<TailingpondReporting> QueryTailingpondReportings(long factoryId, long tailingpondId, DateTime begin, DateTime end, Pagination pagination)
        {
            var reportings = (from r in _dataContext.analysis_reporting_lists
                                   from f in _dataContext.Factories
                                   from t in _dataContext.Tailingponds
                                   from d in _dataContext.tailingpond_analysis_details
                                   where r.status == 3 && f.Id == r.factoryId && r.type == 2 && r.stackId == t.Id && r.stackId == tailingpondId && r.date >= begin && r.date <= end && r.id == d.id
                                   select new TailingpondReporting
                                   {
                                       id = r.id,
                                       date = r.date,
                                       filldam = d.filldam,
                                       backwater = d.backwater,
                                       ditch = d.ditch,
                                       water = d.water,
                                       FactoryName = f.Name,
                                       TailingpondName = t.Name
                                   });

            reportings = from r in reportings
                              orderby r.date descending
                              select r;

            return Pagination<TailingpondReporting>(reportings, pagination);
        }

        public IEnumerable<AnalysisReporting> ListReportings(int year, long userId = 0)
        {
            
            var stackReportings = (from r in _dataContext.analysis_reporting_lists from f in _dataContext.Factories from s in _dataContext.Stacks
                                   where r.date.Year == year && f.Id == r.factoryId && r.type == 1 && r.stackId == s.Id
                              select new AnalysisReporting{
                                 date = r.date,
                                 factoryId = r.factoryId,
                                 finishedTime = r.finishedTime,
                                 id = r.id,
                                 quality = r.quality,
                                 stackId = r.stackId,
                                 status = r.status,
                                 type = r.type,
                                 userId = r.userId,
                                 FactoryName = f.Name,
                                 StackName = s.Name
                              });

            var pondReportings = (from r in _dataContext.analysis_reporting_lists
                                   from f in _dataContext.Factories
                                   from s in _dataContext.Tailingponds
                                  where r.date.Year == year && f.Id == r.factoryId && r.type == 2 && r.stackId == s.Id
                                   select new AnalysisReporting
                                   {
                                       date = r.date,
                                       factoryId = r.factoryId,
                                       finishedTime = r.finishedTime,
                                       id = r.id,
                                       quality = r.quality,
                                       stackId = r.stackId,
                                       status = r.status,
                                       type = r.type,
                                       userId = r.userId,
                                       FactoryName = f.Name,
                                       StackName = s.Name
                                   });

            var reportings = from r in stackReportings.Union(pondReportings) 
                             select r;
            if (userId > 0)
            {
                reportings = from r in reportings
                             where r.userId == userId
                             select r;
            }

            reportings = from r in reportings
                         orderby r.date descending, r.factoryId ascending, r.type ascending
                         select r;

            foreach (AnalysisReporting r in reportings)
            {
                var analyzer = from u in _dataContext.Users
                               where u.Id == r.userId
                               select u;

                if (analyzer != null && analyzer.Count() > 0) r.Analyzer = analyzer.First();
                yield return r;
            }
        }

        public IEnumerable<AnalysisReporting> ListHistoryReportings(int year, long factoryId)
        {

            var stackReportings = (from r in _dataContext.analysis_reporting_lists
                                   from f in _dataContext.Factories
                                   from s in _dataContext.Stacks
                                   where r.date.Year == year && f.Id == r.factoryId && r.type == 1 && r.stackId == s.Id && r.status == 3
                                   select new AnalysisReporting
                                   {
                                       date = r.date,
                                       factoryId = r.factoryId,
                                       finishedTime = r.finishedTime,
                                       id = r.id,
                                       quality = r.quality,
                                       stackId = r.stackId,
                                       status = r.status,
                                       type = r.type,
                                       userId = r.userId,
                                       FactoryName = f.Name,
                                       StackName = s.Name
                                   });

            var pondReportings = (from r in _dataContext.analysis_reporting_lists
                                  from f in _dataContext.Factories
                                  from s in _dataContext.Tailingponds
                                  where r.date.Year == year && f.Id == r.factoryId && r.type == 2 && r.stackId == s.Id && r.status == 3
                                  select new AnalysisReporting
                                  {
                                      date = r.date,
                                      factoryId = r.factoryId,
                                      finishedTime = r.finishedTime,
                                      id = r.id,
                                      quality = r.quality,
                                      stackId = r.stackId,
                                      status = r.status,
                                      type = r.type,
                                      userId = r.userId,
                                      FactoryName = f.Name,
                                      StackName = s.Name
                                  });

            var reportings = from r in stackReportings.Union(pondReportings)
                             select r;
            reportings = from r in reportings
                         where r.factoryId == factoryId
                         select r;

            reportings = from r in reportings
                         orderby r.date descending, r.factoryId ascending, r.type ascending
                         select r;

            foreach (AnalysisReporting r in reportings)
            {
                yield return r;
            }
        }

        public analysis_reporting_list GetReportingByInfo(DateTime date, long factoryId, long stackId, int type)
        {
            var reporting = from r in _dataContext.analysis_reporting_lists
                            where r.date == date && r.factoryId == factoryId && r.stackId == stackId && r.type == type
                            select r;

            if (reporting != null && reporting.Count() > 0)
            {
                return reporting.First();
            }
            else
            {
                return null;
            }
        }

        public analysis_reporting_list GetReportingById(long id)
        {
            var reporting = from r in _dataContext.analysis_reporting_lists
                            where r.id == id
                            select r;

            if (reporting != null && reporting.Count() > 0)
            {
                return reporting.First();
            }
            else
            {
                return null;
            }
        }

        public void CreateReportings()
        {
            DateTime currentMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
            var stacks = from s in _dataContext.Stacks
                         select s;

            var tailingponds = from t in _dataContext.Tailingponds
                               select t;

            for (int i = 0; i < 3; i++)
            {
                foreach(Stack s in stacks)
                {
                    analysis_reporting_list old = GetReportingByInfo(currentMonth, s.FactoryId, s.Id, 1);
                    if (old == null)
                    {
                        analysis_reporting_list reporting = new analysis_reporting_list();
                        reporting.date = currentMonth;
                        reporting.factoryId = s.FactoryId;
                        reporting.stackId = s.Id;
                        reporting.type = 1;
                        reporting.status = 0;
                        _dataContext.analysis_reporting_lists.InsertOnSubmit(reporting);
                    }
                }

                foreach (Tailingpond t in tailingponds)
                {
                    analysis_reporting_list old = GetReportingByInfo(currentMonth, t.FactoryId, t.Id, 2);
                    if (old == null)
                    {
                        analysis_reporting_list reporting = new analysis_reporting_list();
                        reporting.date = currentMonth;
                        reporting.factoryId = t.FactoryId;
                        reporting.stackId = t.Id;
                        reporting.type = 2;
                        reporting.status = 0;
                        _dataContext.analysis_reporting_lists.InsertOnSubmit(reporting);
                    }
                }

                currentMonth = currentMonth.AddMonths(-1);
            }
            SubmitChanges();
        }

        public analysis_reporting_list DistributeReporting(analysis_reporting_list reporting)
        {
            if (reporting.type == 1)
            {
                stack_analysis_detail old = GetStackAnalysis(reporting.id);
                if (old != null)
                {
                    _dataContext.stack_analysis_details.DeleteOnSubmit(old);
                }
                stack_analysis_detail detail = new stack_analysis_detail();
                detail.id = reporting.id;
                _dataContext.stack_analysis_details.InsertOnSubmit(detail);
            }
            else if (reporting.type == 2)
            {
                tailingpond_analysis_detail old = GetTailingpondAnalysis(reporting.id);
                if (old != null)
                {
                    _dataContext.tailingpond_analysis_details.DeleteOnSubmit(old);
                }

                tailingpond_analysis_detail detail = new tailingpond_analysis_detail();
                detail.id = reporting.id;
                _dataContext.tailingpond_analysis_details.InsertOnSubmit(detail);
            }

            SubmitChanges();
            return reporting;
        }

        public stack_analysis_detail GetStackAnalysis(long id)
        {
            var analysis = from a in _dataContext.stack_analysis_details
                           where id == a.id
                           select a;
            if (analysis != null && analysis.Count() > 0)
            {
                return analysis.First();
            }
            else
            {
                return null;
            }
        }

        public tailingpond_analysis_detail GetTailingpondAnalysis(long id)
        {
            var analysis = from a in _dataContext.tailingpond_analysis_details
                           where id == a.id
                           select a;
            if (analysis != null && analysis.Count() > 0)
            {
                return analysis.First();
            }
            else
            {
                return null;
            }
        }

        public analysis_reporting_list UpdateAnalysisReporting(analysis_reporting_list report)
        {
            SubmitChanges();
            return report;
        }

        public stack_analysis_detail UpdateStackAnalysis(stack_analysis_detail report)
        {
            SubmitChanges();
            return report;
        }

        public tailingpond_analysis_detail UpdateTailingpondAnalysis(tailingpond_analysis_detail report)
        {
            SubmitChanges();
            return report;
        }

        public bool DeleteStackAnalysis(long id)
        {
            var reportings = from r in _dataContext.stack_analysis_details
                             where r.id == id
                             select r;

            if (reportings != null && reportings.Count() > 0)
            {
                _dataContext.stack_analysis_details.DeleteOnSubmit(reportings.First());
            }
            return true;
        }

        public bool DeleteTailingpondAnalysis(long id)
        {
            var reportings = from r in _dataContext.tailingpond_analysis_details
                             where r.id == id
                             select r;

            if (reportings != null && reportings.Count() > 0)
            {
                _dataContext.tailingpond_analysis_details.DeleteOnSubmit(reportings.First());
            }
            return true;
        }

        public bool CreateStackAnalysis(stack_analysis_detail report)
        {
            _dataContext.stack_analysis_details.InsertOnSubmit(report);
            _dataContext.SubmitChanges();
            return true;
        }

        public bool CreateTailingpondAnalysis(tailingpond_analysis_detail report)
        {
            _dataContext.tailingpond_analysis_details.InsertOnSubmit(report);
            _dataContext.SubmitChanges();
            return true;
        }
    }
}